"use strict";
var q = require('q');
var BaseCom_1 = require('./../BaseCom');
/** 操作全站仪的com类 */
class GeoCom extends BaseCom_1.BaseCom {
    /**
     * GeoCom的构造函数,立马打开COM口
     * @param {string} portName -  com口的名称
     */
    constructor(portName) {
        super(portName);
        /**
         * @type {string}
         * 串口数据的终止符,\r\n
         */
        this.linebreak = "\r\n";
        /**
         * 判断本次串口数据读取是否结束的函数
         * 全站仪返回的最终数据为\r\n的时候判定本次读取结束
         */
        this._dataComplete = () => {
            let str = this._tempBuffer.toString();
            if (str.length < 2)
                return false;
            let suffix = str.slice(str.length - 2);
            if (suffix === this.linebreak) {
                //最后截掉终止符
                this._tempBuffer = this._tempBuffer.slice(0, this._tempBuffer.length - this.linebreak.length);
                return true;
            }
            else
                return false;
        };
    }
    /**
   * 工厂方法
   * 生产GeoCom数据的处理函数,用来代替父类中的_proccessData函数
   * 对于不同的指令,都可能有不同的操作函数,在这里分为两类:
   * 第一类是有返回值的指令处理,传入返回值的构造函数,在处理的时候构造一个返回值,resolve null表示失败.
   * 注意:返回值类构造函数的属性定义必须按照串口返回数据的顺序来进行
   * 第二类是没有返回值的指令处理,传入null,只需要判断是否成功即可,成功resolve true,失败resolve false
   * @param {Constructor} ResultType 传入对象的构造函数
   * @return {Function} 处理函数
   */
    _dataProcessFactory(ResultType) {
        if (ResultType) {
            /** 对于GeoCom中有返回数据的部分做处理  */
            this._proccessData = () => {
                let str = this._tempBuffer.toString();
                console.log(str);
                let regStr = "%R1P,0,0:0,";
                let reg = new RegExp(regStr);
                if (reg.test(str)) {
                    let valueArray = str.slice(regStr.length).split(',');
                    let resultData = new ResultType();
                    let keys = Object.keys(resultData);
                    if (valueArray.length < keys.length) {
                        //获取的数据长度不够赋值到每个属性,那肯定是结果有错误,直接null
                        this._defer.resolve(null);
                        return;
                    }
                    else {
                        for (let key of keys) {
                            let index = keys.indexOf(key);
                            resultData[key] = parseFloat(valueArray[index]);
                        }
                        this._defer.resolve(resultData);
                    }
                }
                else {
                    this._defer.resolve(null);
                }
            };
        }
        else {
            /** 对于GeoCom中只是指示成功与失败的返回数据处理  */
            this._proccessData = () => {
                let str = this._tempBuffer.toString();
                console.log(str);
                if (str === '%R1P,0,0:0') {
                    this._defer.resolve(true);
                }
                else {
                    this._defer.resolve(false);
                }
            };
        }
    }
    /**
     * 打开或关闭ATR
     * @param {string|number}  toggle - 打开或关闭ATR的参数,'1'或'open'为打开,'0'或'close'为关闭
     * @return {Promise} 返回Promise,成功resolve true,失败resolve false 或 null;
     */
    toggleATR(toggle) {
        if (toggle === 'open')
            toggle = '1';
        if (toggle === 'close')
            toggle = '0';
        this._preSurvey();
        this.port.write(`%R1Q,18005:${toggle}${this.linebreak}`);
        //3秒超时
        this._surveyTimeout(3000);
        //替换数据处理函数
        this._dataProcessFactory(null);
        return this._defer.promise;
    }
    /**
    * 打开或关闭激光
    * @param {string|number}  toggle - 打开或关闭激光的参数,'1'或'open'为打开,'0'或'close'为关闭
    * @return {Promise} 返回Promise,成功resolve true,失败resolve false 或 null;
    */
    toggleLaser(toggle) {
        if (toggle === 'open')
            toggle = '1';
        if (toggle === 'close')
            toggle = '0';
        this._preSurvey();
        this.port.write(`%R1Q,1004:${toggle}${this.linebreak}`);
        //设置超时
        this._surveyTimeout(5000);
        //替换数据处理函数
        this._dataProcessFactory(null);
        return this._defer.promise;
    }
    /**
     * 向目前的照准方向执行测量操作,前提是全站仪已经对准了棱镜或指定的位置
     * @return {Promise<MeasureResult>} 最终返回测量的结果
     */
    measure() {
        this._preSurvey();
        this.port.write("%R1Q,17017:2\r\n");
        this._surveyTimeout(1000 * 15);
        this._dataProcessFactory(MeasureResult);
        return this._defer.promise;
    }
    /**
     * 转动全站仪到指定的位置,默认启用ATR
     * @param {number} hz 指定的水平角,单位弧度
     * @param {number} hv 指定的垂直角,单位弧度
     * @param {boolean} [enableATR=true] 是否使用ATR瞄准,默认采用ATR.不采用时,全站仪仅仅是转向到指定的方位,而不精确对准棱镜
     */
    makePosition(hz, hv, enableATR) {
        let ATR = typeof (enableATR) === 'undefined' ? 1 : (enableATR ? 1 : 0);
        this._preSurvey();
        this.port.write(`%R1Q,9027:${hz},${hv},0,${ATR},0\r\n`);
        this._surveyTimeout(1000 * 15);
        this._dataProcessFactory(null);
        return this._defer.promise;
    }
    /**
     * 切换测量模式,测量模式有两种,有棱镜和无棱镜
     * @param {string} method 要切换的测量方式,RL代表无棱镜,IR代表有棱镜
     */
    toggleMeaureMethod(method) {
        if (typeof method === 'string') {
            if (method.toString().toUpperCase() == "RL") {
                method = "3";
            }
            else if (method.toString().toUpperCase() == "IR") {
                method = "0";
            }
        }
        this._preSurvey();
        this.port.write(`%R1Q,17019:${method}\r\n`);
        this._surveyTimeout(5000);
        this._dataProcessFactory(null);
        return this._defer.promise;
    }
    /**
     * 获取测站坐标
     * @return {object} 测站坐标
     * @property {number} e y坐标
     * @property {number} n x坐标
     * @property {number} h z坐标
     * @property {number} hi 仪器高
     */
    getStationCoor() {
        this._preSurvey();
        this.port.write(`%R1Q,2009:\r\n`);
        this._surveyTimeout(3000);
        this._dataProcessFactory(Coor);
        return this._defer.promise;
    }
    /**
     * 是否串口已经正确的连接到全站仪
     * 该方法调用getStationCoor方法来判断是否连接到全站仪
     * 如果能正确获取到测站坐标,说明全站仪连接正确
     * @return {boolean} true为连接,false为失败
     */
    isTpsConnected() {
        let defer = q.defer();
        this.getStationCoor()
            .then(function (coor) {
                if (coor != null && coor.e != null) {
                    defer.resolve(true);
                }
                else {
                    defer.resolve(false);
                }
            });
        return defer.promise;
    }
}
exports.GeoCom = GeoCom;
class MeasureResult {
    constructor() {
        this.hz = null;
        this.hv = null;
        this.slope = null;
    }
}
exports.MeasureResult = MeasureResult;
class Coor {
    constructor() {
        this.e = null;
        this.n = null;
        this.h = null;
        this.hi = null;
    }
}
exports.Coor = Coor;
var MeasureMethod;
(function (MeasureMethod) {
    MeasureMethod[MeasureMethod["IR"] = 0] = "IR";
    MeasureMethod[MeasureMethod["RL"] = 3] = "RL"; // RL Standard  无棱镜
})(MeasureMethod || (MeasureMethod = {}));
exports.MeasureMethod = MeasureMethod;
;
